package zorm

import (
	_ "github.com/denisenkom/go-mssqldb"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
	_ "github.com/mattn/go-oci8"
	_ "github.com/mattn/go-sqlite3"
	"xorm.io/core"
	"xorm.io/xorm"
	"zorm/consts"
	"zorm/errors"
	"zorm/models"
)

func Open(driverName, dsn string, config *models.Config) (*models.DB, error) {
	var (
		engine interface{}
		err    error
		db     *models.DB
		dbType string
	)
	switch driverName {
	case "mysql", "mymysql", "mssql", "sqlite3", "postgres", "oci8":
		dbType = consts.SqlDatabaseStr
		engine, err = xorm.NewEngine(driverName, dsn)
		engine.(*xorm.Engine).ShowSQL(true)
		convertConfigToXormConfig(engine.(*xorm.Engine), config)
	default:
		return nil, errors.UnsupportDatabaseTypeError
	}
	if err != nil {
		return nil, err
	}
	db = new(models.DB)
	db.DBType = dbType
	db.RealDB = engine
	db.Migrate = &models.Migrator{DBType: dbType, RealDB: engine}
	db.Sessions = &models.Session{
		OperaType: "init",
		Previous:  nil,
		Suffix:    nil,
		Query:     nil,
		Args:      nil,
		Objs:      nil,
	}
	return db, nil
}

func convertConfigToXormConfig(engine *xorm.Engine, config *models.Config) {
	var (
		namerConfig models.NameRule
		tbMapper    core.IMapper
		coMapper    core.IMapper
	)
	namerConfig = config.NameConfig
	if !namerConfig.TableIsSingular {
		tbMapper = core.NewSuffixMapper(core.NewPrefixMapper(core.GonicMapper{}, namerConfig.TablePrefix), "s"+namerConfig.TableSuffix)
	} else {
		tbMapper = core.NewSuffixMapper(core.NewPrefixMapper(core.GonicMapper{}, namerConfig.TablePrefix), namerConfig.TableSuffix)
	}
	engine.SetTableMapper(tbMapper)

	if !namerConfig.ColumnIsSingular {
		coMapper = core.NewSuffixMapper(core.NewPrefixMapper(core.GonicMapper{}, namerConfig.ColumnPrefix), "s"+namerConfig.ColumnSuffix)
	} else {
		coMapper = core.NewSuffixMapper(core.NewPrefixMapper(core.GonicMapper{}, namerConfig.ColumnPrefix), namerConfig.ColumnSuffix)
	}
	engine.SetColumnMapper(coMapper)
}
